home *** CD-ROM | disk | FTP | other *** search
/ Amiga Inside! / Amiga FD Inside (1995)(Ultramax).iso / forumamiga / programme / blkformat / blkformat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-13  |  10.7 KB  |  493 lines

  1. /**
  2.  **  $VER: BlkFormat 1.0 (13-Nov-94) Hanns Holger Rutz
  3.  **
  4.  **  formatiert Textdatei/Clipboardinhalt
  5.  **  (linksbündig, rechtsbündig, zentriert, Blocksatz)
  6.  **
  7.  **  Freeware, benötigt OS2.04+.
  8.  **  Geschrieben mit MaxonC++ 1.1, Tabgröße: 3
  9.  **/
  10.  
  11. #include <exec/types.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <clib/dos_protos.h>
  15. #include <clib/exec_protos.h>
  16. #include <clib/iffparse_protos.h>
  17. #include <exec/memory.h>
  18.  
  19. #define AllocText( tp, s )    {    ULONG sz = (s); struct Text **tptr = (tp);\
  20.                                         if( *tptr = AllocVec( sz + sizeof( **tptr ), MEMF_PUBLIC )) {\
  21.                                             (*tptr)->Length = sz;\
  22.                                             (*tptr)->Data = ((UBYTE *) *tptr) + sizeof( **tptr ); }}
  23. #define FreeText( t ) FreeVec( (APTR) (t) );
  24. #define AllocLine( lp, p, c ) {    struct NewText **lptr = (lp);\
  25.                                             if( *lptr = AllocVec( (c) + sizeof( **lptr ), MEMF_PUBLIC )) {\
  26.                                                 (p)->NextLine = (*lptr);\
  27.                                                 (*lptr)->NextLine = NULL;\
  28.                                                 (*lptr)->Columns = 0;\
  29.                                                 (*lptr)->Data = ((UBYTE *) *lptr) + sizeof( **lptr ); }}
  30. #define FreeLine( l ) FreeVec( (APTR) (l) );
  31.  
  32. #define ID_FTXT    MAKE_ID( 'F', 'T', 'X', 'T' )
  33. #define ID_CHRS    MAKE_ID( 'C', 'H', 'R', 'S' )
  34.  
  35. struct Text        *ReadFile( STRPTR );
  36. struct Text        *ReadClip( LONG );
  37. struct NewText    *ProcessText( struct Text * );
  38. BOOL                 WriteFile( struct NewText *, STRPTR );
  39. BOOL                 WriteClip( struct NewText *, LONG );
  40.  
  41. struct Text {
  42.     ULONG     Length;
  43.     UBYTE    *Data;
  44. };
  45.  
  46. struct NewText {
  47.     struct NewText *NextLine;
  48.     UWORD                 Columns;
  49.     UBYTE                *Data;
  50. };
  51.  
  52. UBYTE Version[]    = "$VER: BlkFormat 1.0 (" __DATE__ ") Hanns Holger Rutz";
  53. UBYTE Template[]    = "FROM,TO,CLIP=CLIPBOARD/K/N,LEFT/S,RIGHT/S,CENTER/S,BLOCK/S,NOMARGIN/S,WIDTH/K/N";
  54.  
  55. UBYTE *IFFErr[] = {
  56.     "Reached logical end of file",
  57.     "About to leave context",
  58.     "No valid scope for property",
  59.     "Internal memory alloc failed",
  60.     "Stream read error",
  61.     "Stream write error",
  62.     "Stream seek error",
  63.     "Data in file is corrupt",
  64.     "IFF syntax error",
  65.     "Not an IFF file",
  66.     "No call-back hook provided",
  67.     "Client handler normal return",
  68.     "Unknown cause"
  69. };
  70. #define NUMERRS (12)
  71.  
  72. struct Library *IFFParseBase = NULL;
  73. LONG                 DefaultWidth = 79;
  74.  
  75. struct {
  76.     STRPTR  From;
  77.     STRPTR  To;
  78.     LONG     *Clip;
  79.     ULONG      Left;
  80.     ULONG      Right;
  81.     ULONG      Center;
  82.     ULONG      Block;
  83.     ULONG      NoMargin;
  84.     LONG     *Width;
  85. } ArgArray = { NULL, NULL, NULL, 0UL, 0UL, 0UL, 0UL, 0UL, &DefaultWidth };
  86.  
  87. int main( void )
  88. {
  89.     int                Res = RETURN_FAIL;
  90.     struct RDArgs *RDArgs;
  91.     
  92.     if( RDArgs = ReadArgs( Template, (LONG *) &ArgArray, NULL ))
  93.     {
  94.         if( (ArgArray.From) || (ArgArray.Clip) )
  95.         {
  96.             struct Text *Tx;
  97.  
  98.             if( (!ArgArray.Left) && (!ArgArray.Right) && (!ArgArray.Center) )
  99.                 ArgArray.Block = TRUE;
  100.  
  101.             if( (ArgArray.From) )    Tx = ReadFile( ArgArray.From );
  102.             else                            Tx = ReadClip( *(ArgArray.Clip) );
  103.     
  104.             if( Tx )
  105.             {
  106.                 BOOL                 Succ;
  107.                 struct NewText *Ln;
  108.                                 
  109.                 if( Ln = ProcessText( Tx ))
  110.                 {
  111.                     if( (ArgArray.To) )            Succ = WriteFile( Ln, ArgArray.To );
  112.                     else {
  113.                         if( (ArgArray.Clip) )    Succ = WriteClip( Ln, *(ArgArray.Clip) );
  114.                         else                            Succ = WriteFile( Ln, ArgArray.From );
  115.                     }
  116.                     if( Succ ) Res = RETURN_OK;
  117.     
  118.                     FreeText( Tx );
  119.                 }
  120.             }
  121.         }
  122.         else PrintFault( ERROR_REQUIRED_ARG_MISSING, NULL );
  123.  
  124.         FreeArgs( RDArgs );
  125.     }
  126.     else PrintFault( IoErr(), NULL );
  127.     
  128.     CloseLibrary( IFFParseBase );
  129.  
  130.     exit( Res );
  131. }
  132.  
  133. VOID LineLength( struct Text *Tx, ULONG *TxOffs, UWORD *Len, UWORD *RealLen,
  134.                       UWORD *Spaces, UWORD *LeadSpaces )
  135. {
  136.     UBYTE LastChar = 0;
  137.     ULONG Start        = *TxOffs;
  138.  
  139.     *Spaces        = 0;
  140.     *LeadSpaces    = 0;
  141.     *Len           = 0;
  142.  
  143.     for( ; *TxOffs < Tx->Length && LastChar != '\n'; (*TxOffs)++ )
  144.     {
  145.         switch( Tx->Data[ *TxOffs ] )
  146.         {
  147.             case ' '    :    if( !(*Len) )
  148.                             {
  149.                                 (*LeadSpaces)++;
  150.                             }
  151.                             else if( LastChar != ' ' )
  152.                             {
  153.                                 (*Spaces)++;
  154.                                 (*Len)++;
  155.                             }
  156.                             LastChar = ' ';
  157.                             break;
  158.  
  159.             case 0x9B:
  160.             case 0x1B:    while( *TxOffs + 1 < Tx->Length
  161.                                      && Tx->Data[ *TxOffs + 1 ] != '\n'
  162.                                      && Tx->Data[ *TxOffs ] != 'm' )
  163.                                 (*TxOffs)++;
  164.                             break;
  165.  
  166.             default:        (*Len)++;
  167.             case '\n':    LastChar = Tx->Data[ *TxOffs ];
  168.                             break;
  169.         }
  170.     }
  171.     *RealLen = (UWORD) (*TxOffs - Start);
  172. }
  173.  
  174. VOID CopyLine( struct NewText *Ln, struct Text *Tx, ULONG Offs, UWORD LeadSpaces,
  175.                     float SpaceWidth )
  176. {
  177.     UBYTE  LastChar = 0;
  178.     UBYTE *Line         = &(Ln->Data[ 0 ]);
  179.     BOOL     Leading     = TRUE;
  180.     float     Remember = 0;
  181.     int     i;
  182.  
  183.     for( ; (LeadSpaces); LeadSpaces-- )
  184.         *(Line++) = ' ';
  185.  
  186.     for( ; Offs < Tx->Length && LastChar != '\n'; Offs++ )
  187.     {
  188.         switch( Tx->Data[ Offs ] )
  189.         {
  190.             case ' '    :    if( LastChar != ' ' && (!Leading) )
  191.                             {
  192.                                 if( !SpaceWidth )
  193.                                 {
  194.                                     *(Line++) = ' ';
  195.                                 }
  196.                                 else
  197.                                 {
  198.                                     i            = (int) (SpaceWidth + Remember + 1.5);
  199.                                     Remember    = SpaceWidth + Remember + 1 - i;
  200.                                     for( ; i > 0; i-- )
  201.                                         *(Line++) = ' ';
  202.                                 }
  203.                                 LastChar     = ' ';
  204.                             }
  205.                             break;
  206.  
  207.             case 0x9B:
  208.             case 0x1B:    do
  209.                             {
  210.                                 *(Line++) = Tx->Data[ Offs ];
  211.                                 Offs++;
  212.                             } while( Offs < Tx->Length && Tx->Data[ Offs ] != '\n'
  213.                                         && Tx->Data[ Offs - 1 ] != 'm' );
  214.                             Offs--;
  215.                             break;
  216.  
  217.             default:        LastChar     = Tx->Data[ Offs ];
  218.                             *(Line++) = LastChar;
  219.                             Leading     = FALSE;
  220.                             break;
  221.         }
  222.     }
  223.     Ln->Columns = (UWORD) (Line - Ln->Data);
  224. }
  225.  
  226. VOID FreeNewText( struct NewText *Ln )
  227. {
  228.     struct NewText *Prev;
  229.     
  230.     while( (Ln) )
  231.     {
  232.         Prev = Ln;
  233.         Ln      = Ln->NextLine;
  234.         FreeLine( Prev );
  235.     }
  236. }
  237.  
  238. struct NewText *ProcessText( struct Text *Tx )
  239. {
  240.     UWORD                 Len,
  241.                          RealLen,
  242.                          Spaces,
  243.                          LeadSpaces;
  244.     WORD                 Diff;
  245.     ULONG                 TxOffs        = 0UL;
  246.     struct NewText *Line            = NULL,
  247.                         *Prev            = NULL,
  248.                         *FirstLine    = NULL;
  249.     
  250.     while( TxOffs < Tx->Length )
  251.     {
  252.         LineLength( Tx, &TxOffs, &Len, &RealLen, &Spaces, &LeadSpaces );
  253.         if( ArgArray.NoMargin ) LeadSpaces = 0;
  254.  
  255.         Prev = Line;
  256.         AllocLine( &Line, Prev, RealLen + *(ArgArray.Width) );
  257.         if( !Line )
  258.         {
  259.             FreeNewText( FirstLine );
  260.             return( NULL );
  261.         }
  262.         if( !Prev ) FirstLine = Line;
  263.         
  264.         if( ArgArray.Block )                // BLOCK
  265.         {
  266.             Diff = *(ArgArray.Width) - Len - LeadSpaces;
  267.             if( (Diff <= 0) || (!Spaces) )
  268.                 CopyLine( Line, Tx, TxOffs - RealLen, LeadSpaces, 0 );
  269.             else
  270.                 CopyLine( Line, Tx, TxOffs - RealLen, LeadSpaces,
  271.                               ((float) Diff) / ((float) Spaces) );
  272.         }
  273.         else
  274.         {
  275.             if( ArgArray.Center )        // CENTER
  276.             {
  277.                 if( Len + 1 >= *(ArgArray.Width) )
  278.                     CopyLine( Line, Tx, TxOffs - RealLen, 0, 0 );
  279.                 else
  280.                     CopyLine( Line, Tx, TxOffs - RealLen,
  281.                                  (*(ArgArray.Width) - Len) >> 1, 0 );
  282.             }
  283.             else
  284.             {
  285.                 if( ArgArray.Right )        // RIGHT
  286.                 {
  287.                     if( Len >= *(ArgArray.Width) )
  288.                         CopyLine( Line, Tx, TxOffs - RealLen, 0, 0 );
  289.                     else
  290.                         CopyLine( Line, Tx, TxOffs - RealLen, *(ArgArray.Width) - Len, 0 );
  291.                 }
  292.                 else
  293.                 {                                // LEFT
  294.                     CopyLine( Line, Tx, TxOffs - RealLen, LeadSpaces, 0 );
  295.                 }
  296.             }
  297.         }
  298.     }
  299.     return( FirstLine );
  300. }
  301.  
  302. struct Text *ReadFile( STRPTR Name )
  303. {
  304.     struct Text                *Tx = NULL;
  305.     struct FileInfoBlock    *fib;
  306.     
  307.     if( fib = AllocDosObject( DOS_FIB, NULL ))
  308.     {
  309.         BPTR fh;
  310.         
  311.         if( fh = Open( Name, MODE_OLDFILE ))
  312.         {
  313.             if( ExamineFH( fh, fib ))
  314.             {
  315.                 AllocText( &Tx, fib->fib_Size );
  316.  
  317.                 if( Tx )
  318.                 {
  319.                     if( Read( fh, Tx->Data, Tx->Length ) == -1 )
  320.                     {
  321.                         PrintFault( IoErr(), Name );
  322.                         FreeText( Tx );
  323.                         Tx = NULL;
  324.                     }
  325.                 }
  326.                 else PrintFault( ERROR_NO_FREE_STORE, NULL );
  327.             }
  328.             else PrintFault( IoErr(), Name );
  329.  
  330.             Close( fh );
  331.         }
  332.         else PrintFault( IoErr(), Name );
  333.  
  334.         FreeDosObject( DOS_FIB, fib );
  335.     }
  336.     else PrintFault( ERROR_NO_FREE_STORE, NULL );
  337.     
  338.     return( Tx );
  339. }
  340.  
  341. BOOL WriteFile( struct NewText *Ln, STRPTR Name )
  342. {
  343.     BPTR fh;
  344.     BOOL Succ = FALSE;
  345.     
  346.     if( fh = Open( Name, MODE_NEWFILE ))
  347.     {
  348.         for( ; (Ln); Ln = Ln->NextLine )
  349.         {
  350.             if( Write( fh, Ln->Data, Ln->Columns ) < 0 ) break;
  351.         }
  352.         Succ = (Ln == NULL);
  353.         if( (!Close( fh )) || (!Succ) )
  354.         {
  355.             Succ = FALSE;
  356.             PrintFault( IoErr(), Name );
  357.         }
  358.     }
  359.     else PrintFault( IoErr(), Name );
  360.     
  361.     return( Succ );
  362. }
  363.  
  364. struct Text *ReadClip( LONG Unit )
  365. {
  366.     struct IFFHandle *iff;
  367.     struct Text          *Tx = NULL;
  368.                 
  369.     if( IFFParseBase == NULL )
  370.     {
  371.         if( !(IFFParseBase = OpenLibrary( "iffparse.library", 36 )))
  372.         {
  373.             PutStr( "Couldn't open `iffparse.library' v36+!\n" );
  374.             return( FALSE );
  375.         }
  376.     }
  377.  
  378.     if( iff = AllocIFF())
  379.     {
  380.         InitIFFasClip( iff );
  381.  
  382.         if( iff->iff_Stream = (ULONG) OpenClipboard( *ArgArray.Clip ))
  383.         {
  384.             LONG Err;
  385.  
  386.             if( !(Err = OpenIFF( iff, IFFF_READ )))
  387.             {
  388.                 if( !(Err = StopChunk( iff, ID_FTXT, ID_CHRS )))
  389.                 {
  390.                     while( (Err = ParseIFF( iff, IFFPARSE_SCAN )) == IFFERR_EOC );
  391.                     
  392.                     if( (!Err) || Err == IFFERR_EOF )
  393.                     {
  394.                         struct ContextNode *cn = CurrentChunk( iff );
  395.                         
  396.                         if( (cn) && cn->cn_Type == ID_FTXT && cn->cn_ID == ID_CHRS )
  397.                         {
  398.                             AllocText( &Tx, cn->cn_Size );
  399.  
  400.                             if( Tx )
  401.                             {
  402.                                 if( ReadChunkBytes( iff, Tx->Data, Tx->Length ) != Tx->Length )
  403.                                 {
  404.                                     Err = IFFERR_READ;
  405.                                     FreeText( Tx );
  406.                                     Tx = NULL;
  407.                                 }
  408.                             }
  409.                             else PrintFault( ERROR_NO_FREE_STORE, NULL );
  410.                         }
  411.                         else VPrintf( "No text in clipboard unit %ld!\n", ArgArray.Clip );
  412.                     }
  413.                 }
  414.             }
  415.             CloseIFF( iff );
  416.             CloseClipboard( (struct ClipboardHandle *) iff->iff_Stream );
  417.  
  418.             if( (Err) && Err != IFFERR_EOF )
  419.             {
  420.                 if( -Err < 1 || -Err > NUMERRS ) Err = -NUMERRS - 1;
  421.                 VPrintf( "Clipboard error: %s\n", (LONG *) &IFFErr[ -Err - 1 ] );
  422.             }
  423.         }
  424.         else VPrintf( "Couldn't open clipboard unit %ld!\n", ArgArray.Clip );
  425.  
  426.         FreeIFF( iff );
  427.     }
  428.     else PrintFault( ERROR_NO_FREE_STORE, NULL );
  429.  
  430.     return( Tx );
  431. }
  432.  
  433. BOOL WriteClip( struct NewText *Ln, LONG Unit )
  434. {
  435.     struct IFFHandle *iff;
  436.     BOOL                    Succ = FALSE;
  437.         
  438.     if( IFFParseBase == NULL )
  439.     {
  440.         if( !(IFFParseBase = OpenLibrary( "iffparse.library", 36 )))
  441.         {
  442.             PutStr( "Couldn't open `iffparse.library' v36+!\n" );
  443.             return( FALSE );
  444.         }
  445.     }
  446.  
  447.     if( iff = AllocIFF())
  448.     {
  449.         InitIFFasClip( iff );
  450.  
  451.         if( iff->iff_Stream = (ULONG) OpenClipboard( *ArgArray.Clip ))
  452.         {
  453.             LONG Err;
  454.  
  455.             if( !(Err = OpenIFF( iff, IFFF_WRITE )))
  456.             {
  457.                 if( !(Err = PushChunk( iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN )))
  458.                 {
  459.                     if( !(Err = PushChunk( iff, 0, ID_CHRS, IFFSIZE_UNKNOWN )))
  460.                     {
  461.                         for( ; (Ln); Ln = Ln->NextLine )
  462.                         {
  463.                             if( WriteChunkBytes( iff, Ln->Data, Ln->Columns ) != Ln->Columns )
  464.                                 break;
  465.                         }
  466.                         if( !Ln )
  467.                         {
  468.                             if( !(Err = PopChunk( iff )))
  469.                                 Err = PopChunk( iff );
  470.                         }
  471.                         else Err = IFFERR_WRITE;
  472.                     }
  473.                 }
  474.             }
  475.             CloseIFF( iff );
  476.             CloseClipboard( (struct ClipboardHandle *) iff->iff_Stream );
  477.  
  478.             if( Err )
  479.             {
  480.                 if( -Err < 1 || -Err > NUMERRS ) Err = -NUMERRS - 1;
  481.                 VPrintf( "Clipboard error: %s\n", (LONG *) &IFFErr[ -Err - 1 ] );
  482.             }
  483.             else Succ = TRUE;
  484.         }
  485.         else VPrintf( "Couldn't open clipboard unit %ld!\n", ArgArray.Clip );
  486.  
  487.         FreeIFF( iff );
  488.     }
  489.     else PrintFault( ERROR_NO_FREE_STORE, NULL );
  490.  
  491.     return( Succ );
  492. }
  493.